<?php


namespace App\Http\Controllers\Admin\Statistics;


use App\Enums\GiftTypeEnum;
use App\Enums\MallEnum;
use App\Enums\GameEnum;
use App\Response\Response;
use App\Request\Validator;
use Illuminate\Http\Request;
use App\Services\Tools\DateTime;
use App\Exceptions\BasicException;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\BaseController;

//数据统计
class StatisticsController extends BaseController
{
    private $serialFields = ['room_gift_serial', 'blind_box_serial', 'lucky_tree_serial', 'scramble_sugar_serial','star_wishing_serial', 'ad_astra_serial'];

    /**
     * @api {get} /statistics/room-serial/total 房间流水统计
     *
     * @apiGroup 数据看板-房间流水
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": {
    "day_data": [ 日数据：
    {
    "room_gift_serial": { 房间礼物流水：
    "last_serial": "0", 上期流水（下同）
    "this_serial": "520", 本期流水（下同）
    "change_rate": "" 变化率（下同）
    }
    },
    {
    "blind_box_serial": { 盲盒流水：
    "last_serial": "0",
    "this_serial": "244700",
    "change_rate": ""
    }
    },
    {
    "lucky_tree_serial": { 许愿流星流水：
    "last_serial": "0",
    "this_serial": "788400",
    "change_rate": ""
    }
    },
    {
    "scramble_sugar_serial": { 抢糖流水：
    "last_serial": "0",
    "this_serial": "0",
    "change_rate": ""
    }
    },
    {
    "huoke_serial": { 霍克城堡流水：
    "last_serial": "0",
    "this_serial": "0",
    "change_rate": ""
    }
    },
    {
    "total": { 总计：
    "last_serial": "0",
    "this_serial": "1033620",
    "change_rate": ""
    }
    }
    ],
    "week_data": [ 周数据：
    {
    "room_gift_serial": {
    "last_serial": "7516373693",
    "this_serial": "143839907",
    "change_rate": "降5125.51%"
    }
    },
    {
    "blind_box_serial": {
    "last_serial": "39113241",
    "this_serial": "4681346",
    "change_rate": "降735.51%"
    }
    },
    {
    "lucky_tree_serial": {
    "last_serial": "86727804",
    "this_serial": "9725010",
    "change_rate": "降791.8%"
    }
    },
    {
    "scramble_sugar_serial": {
    "last_serial": "0",
    "this_serial": "0",
    "change_rate": ""
    }
    },
    {
    "huoke_serial": {
    "last_serial": "2008064",
    "this_serial": "394074",
    "change_rate": "降409.57%"
    }
    },
    {
    "total": {
    "last_serial": "7644222802",
    "this_serial": "158640337",
    "change_rate": "降4718.59%"
    }
    }
    ],
    "month_data": [ 月数据：
    {
    "room_gift_serial": {
    "last_serial": "11927600383",
    "this_serial": "8367190703",
    "change_rate": "降42.55%"
    }
    },
    {
    "blind_box_serial": {
    "last_serial": "110202254",
    "this_serial": "60775881",
    "change_rate": "降81.33%"
    }
    },
    {
    "lucky_tree_serial": {
    "last_serial": "250597309",
    "this_serial": "185080503",
    "change_rate": "降35.4%"
    }
    },
    {
    "scramble_sugar_serial": {
    "last_serial": "1502",
    "this_serial": "1",
    "change_rate": "降150100%"
    }
    },
    {
    "huoke_serial": {
    "last_serial": "103745078",
    "this_serial": "3194685",
    "change_rate": "降3147.43%"
    }
    },
    {
    "total": {
    "last_serial": "12392146526",
    "this_serial": "8616241773",
    "change_rate": "降43.82%"
    }
    }
    ]
    }
    }
     */
    public function roomSerialTotalOld()
    {
        //按日
        $yesterday = date('Y-m-d', strtotime("-1 day"));
        $today = date('Y-m-d');
        $yesterdaySerial = app('model_system_everyday_serial')->getSum($this->serialFields, $yesterday);
        $todaySerial = app('model_system_everyday_serial')->getSum($this->serialFields, $today);
        //计算流水变化率
        $todaySerialChangeRate = app('repo_data_statistics')->calculateRoomSerialChangeRate($yesterdaySerial, $todaySerial);

        //按周
        $lastWeekDateRange = DateTime::getWeekDateRange(-1);
        $thisWeekDateRange = DateTime::getWeekDateRange();
        $lastWeekSerial = app('model_system_everyday_serial')->getSum($this->serialFields, $lastWeekDateRange);
        $thisWeekSerial = app('model_system_everyday_serial')->getSum($this->serialFields, $thisWeekDateRange);
        $thisWeekSerialChangeRate = app('repo_data_statistics')->calculateRoomSerialChangeRate($lastWeekSerial, $thisWeekSerial);

        //按月
        $lastMonthDateRange = DateTime::getMonthDateRange(-1);
        $thisMonthDateRange = DateTime::getMonthDateRange();
        $lastMonthSerial = app('model_system_everyday_serial')->getSum($this->serialFields, $lastMonthDateRange);
        $thisMonthSerial = app('model_system_everyday_serial')->getSum($this->serialFields, $thisMonthDateRange);
        $thisMonthSerialChangeRate = app('repo_data_statistics')->calculateRoomSerialChangeRate($lastMonthSerial, $thisMonthSerial);

        //转换一下数据返回格式
        $dayData = [];
        foreach ($yesterdaySerial as $k => $v) {
            $dayData[] = [
                $k => [
                    'last_serial' => $yesterdaySerial[$k],
                    'this_serial' => $todaySerial[$k],
                    'change_rate' => $todaySerialChangeRate[$k],
                ],
            ];
        }

        $weekData = [];
        foreach ($lastWeekSerial as $k => $v) {
            $weekData[] = [
                $k => [
                    'last_serial' => $lastWeekSerial[$k],
                    'this_serial' => $thisWeekSerial[$k],
                    'change_rate' => $thisWeekSerialChangeRate[$k],
                ],
            ];
        }

        $monthData = [];
        foreach ($lastMonthSerial as $k => $v) {
            $monthData[] = [
                $k => [
                    'last_serial' => $lastMonthSerial[$k],
                    'this_serial' => $thisMonthSerial[$k],
                    'change_rate' => $thisMonthSerialChangeRate[$k],
                ],
            ];
        }

        return Response::sendData([
            'day_data' => $dayData,
            'week_data' => $weekData,
            'month_data' => $monthData,
        ]);
    }

    public function roomSerialTotal()
    {
        /**按日**/
        //今日流水
        $today = date('Y-m-d');
        $todaySerial = app('model_system_everyday_serial')->getSum($this->serialFields, $today);

        //昨天流水
        $yesterday = date('Y-m-d', strtotime("-1 day"));
        $yesterdaySerial = app('model_system_everyday_serial')->getSum($this->serialFields, $yesterday);

        //前天流水
        $lastLastDay = date('Y-m-d', strtotime("-2 day"));
        $lastLastDaySerial = app('model_system_everyday_serial')->getSum($this->serialFields, $lastLastDay);

        //今日此时流水
        $startTimestamp = strtotime(date('Y-m-d') . ' 00:00:00');
        $endTimestamp = time();
        $todayThisSerial = $this->getFormatSerialArr([$startTimestamp, $endTimestamp]);

        //昨日此时流水
        $yesterdayThisSerial = $this->getFormatSerialArr([$startTimestamp - 86400, $startTimestamp - 1]);

        //今日此时对比昨日此时变化率
        $daySerialChangeRate = app('repo_data_statistics')->calculateRoomSerialChangeRate($lastLastDaySerial,$yesterdayThisSerial);

        /**按周**/
        //上上周流水
        $lastLastWeekDateRange = DateTime::getWeekDateRange(-2);
        $lastLastWeekSerial = app('model_system_everyday_serial')->getSum($this->serialFields, $lastLastWeekDateRange);

        //上周流水
        $lastWeekDateRange = DateTime::getWeekDateRange(-1);
        $lastWeekSerial = app('model_system_everyday_serial')->getSum($this->serialFields, $lastWeekDateRange);

        //本周流水
        $thisWeekDateRange = DateTime::getWeekDateRange();
        $thisWeekSerial = app('model_system_everyday_serial')->getSum($this->serialFields, $thisWeekDateRange);

        $weekSerialChangeRate = app('repo_data_statistics')->calculateRoomSerialChangeRate($lastLastWeekSerial, $lastWeekSerial);

        /**按月**/
        $lastLastMonthDateRange = DateTime::getMonthDateRange(-2);
        $lastLastMonthSerial = app('model_system_everyday_serial')->getSum($this->serialFields, $lastLastMonthDateRange);

        $lastMonthDateRange = DateTime::getMonthDateRange(-1);
        $lastMonthSerial = app('model_system_everyday_serial')->getSum($this->serialFields, $lastMonthDateRange);

        $thisMonthDateRange = DateTime::getMonthDateRange();
        $thisMonthSerial = app('model_system_everyday_serial')->getSum($this->serialFields, $thisMonthDateRange);

        $monthSerialChangeRate = app('repo_data_statistics')->calculateRoomSerialChangeRate($lastLastMonthSerial, $lastMonthSerial);

        //转换一下数据返回格式
        $dayData = [];
        foreach ($yesterdaySerial as $k => $v) {
            $dayData[] = [
                $k => [
                    'last_last_serial' => $lastLastDaySerial[$k],
                    'last_serial' => $yesterdaySerial[$k],
                    'this_serial' => $todaySerial[$k],
                    'change_rate' => $daySerialChangeRate[$k],
                ],
            ];
        }

        $weekData = [];
        foreach ($lastWeekSerial as $k => $v) {
            $weekData[] = [
                $k => [
                    'last_last_serial' => $lastLastWeekSerial[$k],
                    'last_serial' => $lastWeekSerial[$k],
                    'this_serial' => $thisWeekSerial[$k],
                    'change_rate' => $weekSerialChangeRate[$k],
                ],
            ];
        }

        $monthData = [];
        foreach ($lastMonthSerial as $k => $v) {
            $monthData[] = [
                $k => [
                    'last_last_serial' => $lastLastMonthSerial[$k],
                    'last_serial' => $lastMonthSerial[$k],
                    'this_serial' => $thisMonthSerial[$k],
                    'change_rate' => $monthSerialChangeRate[$k],
                ],
            ];
        }

        return Response::sendData([
            'day_data' => $dayData,
            'week_data' => $weekData,
            'month_data' => $monthData,
        ]);
    }

    private function getFormatSerialArr($timestampRange)
    {
        $data = [
            "room_gift_serial" => app('repo_data_statistics')->querySystemSerial(GiftTypeEnum::getGiftType('room_gift'), $timestampRange),
            "blind_box_serial" => app('repo_data_statistics')->querySystemSerial(GiftTypeEnum::getGiftType('magic_gift_config'), $timestampRange),
            "ad_astra_serial" => app('repo_data_statistics')->querySystemSerial(GiftTypeEnum::getGiftType('ad_astra'), $timestampRange),
            "lucky_tree_serial" => app('repo_data_statistics')->querySystemSerial(GiftTypeEnum::getGiftType('tree_gift'), $timestampRange),
            "scramble_sugar_serial" => app('repo_data_statistics')->querySystemSerial(GiftTypeEnum::getGiftType('candies'), $timestampRange),
            "star_wishing_serial" => app('repo_data_statistics')->querySystemSerial(GiftTypeEnum::getGiftType('happy'), $timestampRange),
        ];
        $data['total'] = 0;
        foreach ($data as $serial) {
            $data['total'] += $serial;
        }

        return $data;
    }

    /**
     * @api {get} /statistics/room-serial 房间流水列表
     *
     * @apiGroup 数据看板-房间流水
     *
     * @apiParam {Int} date_tag 日期标签：-1(默认)：不限制；0：自定义，需要传开始和结束日期；1：今日；2：本周；3：本月
     * @apiParam {string} start_date 开始日期，yyyy-mm-dd
     * @apiParam {string} end_date 结束日期，yyyy-mm-dd
     * @apiParam {Int} room_id 房间ID
     * @apiParam {Int} page 第几页，默认1
     * @apiParam {Int} page_size 每页显示条数，默认10
     * @apiParam {Int} order_by_room_gift 按房间礼物流水排序：-1：降序；0：不排序；1：升序（下同）
     * @apiParam {Int} order_by_blind_box 按盲盒流水排序
     * @apiParam {Int} order_by_lucky_tree 按许愿流星流水排序
     * @apiParam {Int} order_by_scramble_sugar 按抢糖流水排序
     * @apiParam {Int} order_by_huoke 按霍克城堡流水排序
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": {
    "current_page": 1,
    "data": [
    {
    "room_id": 765,
    "room_gift_serial": 436, 房间礼物流水
    "blind_box_serial": 346, 盲盒流水
    "lucky_tree_serial": 765, 许愿流星流水
    "scramble_sugar_serial": 765, 抢糖流水
    "huoke_serial": 561, 霍克城堡流水
    "total": 2873, 总计
    "room_info": { 房间信息：
    "id": 765,
    "room_id": 4167430, 房间ID
    "room_name": "打野" 房间名称
    }
    }
    ],
    "first_page_url": "http://local.qipaoadmin/statistics/room-serial?page=1",
    "from": 1,
    "last_page": 1,
    "last_page_url": "http://local.qipaoadmin/statistics/room-serial?page=1",
    "next_page_url": null,
    "path": "http://local.qipaoadmin/statistics/room-serial",
    "per_page": 15,
    "prev_page_url": null,
    "to": 1,
    "total": 1
    }
    }
     */
    public function roomSerialList(Request $request)
    {
        $params = $request->only('date_tag', 'start_date', 'end_date', 'room_id', 'page', 'page_size', 'order_by_room_gift', 'order_by_blind_box', 'order_by_lucky_tree', 'order_by_scramble_sugar', 'order_by_huoke');
        $v = app('validator')->make($params, [
            'date_tag' => 'integer|in:-1,0,1,2,3',
            'start_date' => 'required_if:date_tag,0|date_format:Y-m-d',
            'end_date' => 'required_if:date_tag,0|date_format:Y-m-d',
            'room_id' => 'integer',
            'page' => 'integer|min:1',
            'page_size' => 'integer|min:1|max:100',
            'order_by_room_gift' => 'integer|in:-1,0,1',
            'order_by_blind_box' => 'integer|in:-1,0,1',
            'order_by_lucky_tree' => 'integer|in:-1,0,1',
            'order_by_scramble_sugar' => 'integer|in:-1,0,1',
            'order_by_huoke' => 'integer|in:-1,0,1',
        ]);
        if ($v->fails()) throw new BasicException(0, $v->errors()->first());

        $dateTag = $params['date_tag'] ?? -1;
        $startDate = $params['start_date'] ?? '';
        $endDate = $params['end_date'] ?? '';
        $roomId = $params['room_id'] ?? 0;
        $pageSize = $params['page_size'] ?? 10;
        $orderByRoomGift = $params['order_by_room_gift'] ?? 0;
        $orderByBlindBox = $params['order_by_blind_box'] ?? 0;
        $orderByLuckyTree = $params['order_by_lucky_tree'] ?? 0;
        $orderByAdAstra = $params['order_by_ad_astra'] ?? 0;
        $orderByStarWishing = $params['order_by_star_wishing'] ?? 0;
        $orderByScrambleSugar = $params['order_by_scramble_sugar'] ?? 0;
        $orderByHuoke = $params['order_by_huoke'] ?? 0;

        if ($dateTag == 0 && strtotime($endDate) - strtotime($startDate) > 180 * 86400) {
            throw new BasicException(0, '日期范围不能超过180天');
        }

        $where = [];
        if ($roomId) {
            $roomId = app('model_user_room')->where('room_id', $roomId)->value('id');
            $where[] = ['room_id', '=', $roomId];
        }
        if ($orderByRoomGift != 0) {
            $sortField = 'room_gift_serial';
            $sortVar = $orderByRoomGift;
        } else if ($orderByBlindBox != 0) {
            $sortField = 'blind_box_serial';
            $sortVar = $orderByBlindBox;
        } else if ($orderByLuckyTree != 0) {
            $sortField = 'lucky_tree_serial';
            $sortVar = $orderByLuckyTree;
        } else if ($orderByScrambleSugar != 0) {
            $sortField = 'scramble_sugar_serial';
            $sortVar = $orderByScrambleSugar;
        } else if ($orderByHuoke != 0) {
            $sortField = 'huoke_serial';
            $sortVar = $orderByHuoke;
        } else if ($orderByAdAstra != 0) {
            $sortField = 'ad_astra_serial';
            $sortVar = $orderByAdAstra;
        } else if ($orderByStarWishing != 0) {
            $sortField = 'star_wishing_serial';
            $sortVar = $orderByStarWishing;
        }
        if (isset($sortVar) && $sortVar == -1) {
            $sortMethod = 'desc';
        } else {
            $sortMethod = 'asc';
        }

        if ($dateTag == -1) {
            $model = app('model_system_room_serial');
        } else {
            $model = app('model_system_room_everyday_serial');

            if ($dateTag == 0) {
                $dateRange = [$startDate, $endDate];
            } else if ($dateTag == 1) {
                $dateRange = [date('Y-m-d'), date('Y-m-d')];
            } else if ($dateTag == 2) {
                $dateRange = DateTime::getWeekDateRange();
            } else if ($dateTag == 3) {
                $dateRange = DateTime::getMonthDateRange();
            }
        }

        $fieldSum = $fieldSumTotal = '';
        foreach ($this->serialFields as $field) {
            $fieldSum .= "sum($field) as $field,";
            $fieldSumTotal .= "sum($field)+";
        }
        $fieldSum = rtrim($fieldSum, ',');
        $fieldSumTotal = rtrim($fieldSumTotal, '+') . ' as total';
        $list = $model->select('room_id', DB::raw($fieldSum), DB::raw($fieldSumTotal))->where($where);
        if (isset($dateRange)) {
            $list = $list->whereBetween('date', $dateRange);
        }
        $list = $list->groupBy('room_id');
        if (isset($sortField)) {
            $list = $list->orderBy($sortField, $sortMethod);
        }
        $list = $list->with(['room_info' => function ($query) {
            $query->select('id', 'room_id', 'room_name');
        }])->paginate($pageSize);

        return Response::sendData($list);
    }

    /**
     * 获取今天的小时折线图
     * @param $roomId
     * @param null $date
     * @return array
     */
    private function roomTodayPicture($roomId, $type, $date = null)
    {
        if (empty($date)) $date = date('Y-m-d');
        $timestampRange = DateTime::getDateTimestampRange($date);

        //查询日期内所有送礼记录
        $roomSerialTotal = [];
        for ($i=0;$i<24;$i++) {
            if (strlen($i) == 1) {
                $roomSerialTotal['0' . $i] = 0;
            } else {
                $roomSerialTotal[$i] = 0;
            }
        }

        $serialFields = [
            'room_gift',
            'magic_gift_config',
            'tree_gift',
            'candies',
            'happy'
        ];
        //查询类型下的礼物id
        $giftIds = [];
        if ($type != -1) {
            $serialKey = $serialFields[$type];
            $giftType = GiftTypeEnum::getGiftType($serialKey);
            $giftIds = app('model_gift')->getGiftIdsByType($giftType);
        } else {
            foreach ($serialFields as $value) {
                $giftType = GiftTypeEnum::getGiftType($value);
                $giftId = app('model_gift')->getGiftIdsByType($giftType);
                $giftIds = array_merge($giftIds,$giftId);
            }
            $giftIds = array_unique($giftIds);
        }
        $giveGiftRecords = app('model_give_gift')
            ->select('room_id', 'gift_id', 'total_price', 'add_time')
            ->whereBetween('add_time', $timestampRange)
            ->where('room_id', '=', $roomId)
            ->whereIn('gift_id', $giftIds)
            ->orderBy('add_time','asc')
            ->get()->toArray();

        foreach ($giveGiftRecords as $giftRecord) {
            $k = date('H',$giftRecord['add_time']);
            $roomSerialTotal[$k] += $giftRecord['total_price'];
        }
        return $roomSerialTotal;
    }

    /**
     * 房间列表折线图
     * @param Request $request
     * @return string
     * @throws BasicException
     */
    public function roomSerialListPicture(Request $request)
    {
        $params = $request->only('date_tag', 'start_date', 'end_date', 'room_id', 'type');
        $v = app('validator')->make($params, [
            'date_tag' => 'integer|in:-1,0,1,2,3',
            'start_date' => 'required_if:date_tag,0|date_format:Y-m-d',
            'end_date' => 'required_if:date_tag,0|date_format:Y-m-d',
            'room_id' => 'integer',
            'type' => 'integer',
        ]);
        if ($v->fails()) throw new BasicException(0, $v->errors()->first());

        $dateTag = $params['date_tag'] ?? -1;
        $startDate = $params['start_date'] ?? '';
        $endDate = $params['end_date'] ?? '';
        $roomId = $params['room_id'] ?? 0;
        $type = $params['type'] ?? -1;

        if ($roomId == 0 && $dateTag == 0) {
            return Response::sendData([]);
        }

        $dateRange = [$startDate, $endDate];
        if ($dateTag == 0 && strtotime($endDate) - strtotime($startDate) > 180 * 86400) {
            throw new BasicException(0, '日期范围不能超过180天');
        }

        $where = [];
        if ($roomId) {
            $roomId = app('model_user_room')->where('room_id', $roomId)->value('id');
            $where[] = ['room_id', '=', $roomId];
        }

        if ($dateTag == -1) {
            $model = app('model_system_room_serial');
        } else {
            if ($dateTag == 1) {
                $list = $this->roomTodayPicture($roomId, $type);
                return Response::sendData($list);
            } else {
                $model = app('model_system_room_everyday_serial');
            }

            if ($dateTag == 2) {
                $dateRange = DateTime::getWeekDateRange();
            } else if ($dateTag == 3) {
                $pageSize = 31;
                $dateRange = DateTime::getMonthDateRange();
            } else if ($dateTag == 0) {
                $dateRange = [$startDate,$endDate];
            }
        }

        $fieldSum = $fieldSumTotal = '';
        if ($type == -1) {
            foreach ($this->serialFields as $field) {
                $fieldSum .= "sum($field) as $field,";
                $fieldSumTotal .= "sum($field)+";
            }
        } else {
            $serialFields = [
                'room_gift_serial',
                'blind_box_serial',
                'lucky_tree_serial',
                'scramble_sugar_serial',
                'star_wishing_serial'
            ];
            //查询类型下的礼物id
            $field = $serialFields[$type];
            $fieldSum .= "sum($field) as $field,";
            $fieldSumTotal .= "sum($field)+";
        }

        $fieldSum = rtrim($fieldSum, ',');
        $fieldSumTotal = rtrim($fieldSumTotal, '+') . ' as total';
        $list = $model->select('room_id', 'date', DB::raw($fieldSumTotal))->where($where);
        if (isset($dateRange)) {
            $list = $list->whereBetween('date', $dateRange);
        }
        $list = $list->where('room_id', $roomId)->orderBy('date','asc')->groupBy('date');
        $list = $list->with(['room_info' => function ($query) {
            $query->select('id', 'room_id', 'room_name');
        }])->get()->toArray();

        return Response::sendData($list);
    }

    /**
     * @api {get} /statistics/room-serial/refresh 刷新系统流水数据
     *
     * @apiGroup 数据看板-房间流水
     *
     * @apiSuccessExample {json} Response-Example
     * {"code":200,"data":[]}
     */
    public function refreshSystemSerial()
    {
        $minRefreshInterval = 5; //最小刷新间隔，单位：分钟
        $lastUpdateTime = app('model_system_everyday_serial')->getLatestUpdateTime();
        if (time() - strtotime($lastUpdateTime) > $minRefreshInterval * 60) {
            //系统今日流水统计
            app('repo_data_statistics')->systemTodaySerial();
            //房间今日流水统计
            app('repo_data_statistics')->roomTodaySerial();
            //房间总流水统计
            app('repo_data_statistics')->roomSerial();
            //商城每日流水
            app('repo_data_statistics')->mallTodaySerial();
        }
        return Response::sendData([]);
    }

    /**
     * @api {get} /statistics/mall-serial/total 商城流水统计
     *
     * @apiGroup 数据看板-商城流水
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": {
    "day_data": [ //日数据：
    {
    "category_name": "挂件", 商品分类名称
    "last_serial": 0, 上期流水
    "this_serial": "999", 本期流水
    "change_rate": "" 变化率
    },
    {
    "category_name": "坐骑",
    "last_serial": "7366",
    "this_serial": "1411",
    "change_rate": "降422.04%"
    },
    {
    "category_name": "入场特效",
    "last_serial": "3000",
    "this_serial": 0,
    "change_rate": "降100%"
    },
    {
    "category_name": "聊天气泡",
    "last_serial": 0,
    "this_serial": 0,
    "change_rate": ""
    },
    {
    "category_name": "公屏气泡",
    "last_serial": 0,
    "this_serial": 0,
    "change_rate": ""
    },
    {
    "category_name": "声波",
    "last_serial": 0,
    "this_serial": 0,
    "change_rate": ""
    },
    {
    "category_name": "全服广播",
    "last_serial": 0,
    "this_serial": 0,
    "change_rate": ""
    },
    {
    "category_name": "昵称挂件",
    "last_serial": 0,
    "this_serial": 0,
    "change_rate": ""
    },
    {
    "category_name": "昵称特效",
    "last_serial": 0,
    "this_serial": 0,
    "change_rate": ""
    }
    ],
    "week_data": [ 周数据：
    {
    "category_name": "挂件",
    "last_serial": "7200",
    "this_serial": "13998",
    "change_rate": "增48.56%"
    },
    {
    "category_name": "坐骑",
    "last_serial": "12066",
    "this_serial": "14777",
    "change_rate": "增18.35%"
    },
    {
    "category_name": "入场特效",
    "last_serial": "2110",
    "this_serial": "3000",
    "change_rate": "增29.67%"
    },
    {
    "category_name": "聊天气泡",
    "last_serial": "3700",
    "this_serial": 0,
    "change_rate": "降100%"
    },
    {
    "category_name": "公屏气泡",
    "last_serial": "3700",
    "this_serial": 0,
    "change_rate": "降100%"
    },
    {
    "category_name": "声波",
    "last_serial": "705694",
    "this_serial": "109399",
    "change_rate": "降545.06%"
    },
    {
    "category_name": "全服广播",
    "last_serial": "4900",
    "this_serial": 0,
    "change_rate": "降100%"
    },
    {
    "category_name": "昵称挂件",
    "last_serial": "32000698",
    "this_serial": "3000",
    "change_rate": "降1066589.93%"
    },
    {
    "category_name": "昵称特效",
    "last_serial": "3700",
    "this_serial": 0,
    "change_rate": "降100%"
    }
    ],
    "month_data": [ 月数据：
    {
    "category_name": "挂件",
    "last_serial": "2266326",
    "this_serial": "60598",
    "change_rate": "降3639.94%"
    },
    {
    "category_name": "坐骑",
    "last_serial": "1658027",
    "this_serial": "74766",
    "change_rate": "降2117.62%"
    },
    {
    "category_name": "入场特效",
    "last_serial": "17000",
    "this_serial": "11610",
    "change_rate": "降46.43%"
    },
    {
    "category_name": "聊天气泡",
    "last_serial": "7200",
    "this_serial": "7400",
    "change_rate": "增2.7%"
    },
    {
    "category_name": "公屏气泡",
    "last_serial": "31200",
    "this_serial": "8800",
    "change_rate": "降254.55%"
    },
    {
    "category_name": "声波",
    "last_serial": "6500",
    "this_serial": "2022284",
    "change_rate": "增99.68%"
    },
    {
    "category_name": "全服广播",
    "last_serial": "3000",
    "this_serial": "7900",
    "change_rate": "增62.03%"
    },
    {
    "category_name": "昵称挂件",
    "last_serial": "4200",
    "this_serial": "97604386",
    "change_rate": "增100%"
    },
    {
    "category_name": "昵称特效",
    "last_serial": "22200",
    "this_serial": "7400",
    "change_rate": "降200%"
    }
    ]
    }
    }
     */
    public function mallSerialTotal()
    {
        //获取所有分类
        $categoryIds = app('model_mall_categories')->getAllSubCateId(MallEnum::PRODUCT_CATE_ID_ALL);
        //分类id与名称的映射
        $categoryIdNameMap = app('model_mall_categories')->whereIn('id', $categoryIds)->pluck('title', 'id')->toArray();

        //按日
        $today = date('Y-m-d');
        $yesterday = date('Y-m-d', strtotime("-1 day"));
        $lastLastDay = date('Y-m-d', strtotime("-2 day"));
        //按周
        $thisWeekDateRange = DateTime::getWeekDateRange();
        $lastWeekDateRange = DateTime::getWeekDateRange(-1);
        $lastLastWeekDateRange = DateTime::getWeekDateRange(-2);
        //按月
        $thisMonthDateRange = DateTime::getMonthDateRange();
        $lastMonthDateRange = DateTime::getMonthDateRange(-1);
        $lastLastMonthDateRange = DateTime::getMonthDateRange(-2);

        $dayData = $weekData = $monthData = [];
        foreach ($categoryIds as $categoryId) {
            $dayData[] = $this->formatMallSerialData($categoryIdNameMap, $categoryId, $today, $yesterday, $lastLastDay);
            $weekData[] = $this->formatMallSerialData($categoryIdNameMap, $categoryId, $thisWeekDateRange, $lastWeekDateRange, $lastLastWeekDateRange);
            $monthData[] = $this->formatMallSerialData($categoryIdNameMap, $categoryId, $thisMonthDateRange, $lastMonthDateRange, $lastLastMonthDateRange);
        }

        $data = [
            'day_data' => $dayData,
            'week_data' => $weekData,
            'month_data' => $monthData,
        ];
        return Response::sendData($data);
    }

    private function formatMallSerialData(&$categoryIdNameMap, $categoryId, $thisDate, $lastDate, $lastLastDate)
    {
        $thisSerialTotal = app('model_mall_everyday_serial')->getSum($thisDate, $categoryId);
        $lastSerialTotal = app('model_mall_everyday_serial')->getSum($lastDate, $categoryId);
        $lastLastSerialTotal = app('model_mall_everyday_serial')->getSum($lastLastDate, $categoryId);

        $changeRate = app('repo_data_statistics')->calculateChangeValue($lastLastSerialTotal, $lastSerialTotal);
        return [
            'category_name' => $categoryIdNameMap[$categoryId] ?? '',
            'this_serial' => $thisSerialTotal,
            'last_serial' => $lastSerialTotal,
            'last_last_serial' => $lastLastSerialTotal,
            'change_rate' => $changeRate,
        ];
    }

    /**
     * @api {get} /statistics/user/hourly-count 用户登录注册数量统计
     *
     * @apiGroup 数据看板-数据看板
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": [
    {
    "date": "2021-09-28", 日期
    "start_hour": 14, 开始小时
    "end_hour": 15, 结束小时
    "register_count": 4, 注册人数
    "login_count": 8 登录人数
    }
    ],
    "message": ""
    }
     */
    public function hourlyUserCount(Request $request)
    {
        $fields = ['date_tag', 'start_date', 'end_date'];
        $params = $request->only($fields);
        Validator::paramVerify($fields, $params);

        $dateTag = $params['date_tag'] ?? -1;
        $startDate = $params['start_date'] ?? '';
        $endDate = $params['end_date'] ?? '';

        //计算日期范围
        $dateRange = DateTime::getDateRangeByTag($dateTag, $startDate, $endDate);

        $data = app('model_statistics_user_count')
            ->select('date', 'start_hour', 'end_hour', 'register_count', 'login_count')
            ->where(function ($query) use ($dateRange) {
                if (is_array($dateRange)) {
                    $query->whereBetween('date', $dateRange);
                } else {
                    $query->where('date', $dateRange);
                }
            })
            ->get()->toArray();
        return Response::sendData($data);
    }

    /**
     * @api {get} /statistics/user/amount 用户金额统计（充值、提现）
     *
     * @apiGroup 数据看板-数据看板
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": [
    {
    "date": "2021-09-28", 日期
    "recharge_amount": "0.00", 充值金额
    "withdraw_amount": "0.00" 提现金额
    }
    ],
    "message": ""
    }
     */
    public function userAmount(Request $request)
    {
        $fields = ['date_tag', 'start_date', 'end_date'];
        $params = $request->only($fields);
        Validator::paramVerify($fields, $params);

        $dateTag = $params['date_tag'] ?? -1;
        $startDate = $params['start_date'] ?? '';
        $endDate = $params['end_date'] ?? '';

        //计算日期范围
        $dateRange = DateTime::getDateRangeByTag($dateTag, $startDate, $endDate);

        $data = app('model_statistics_user_amount')
            ->select('date', 'recharge_amount', 'withdraw_amount')
            ->where(function ($query) use ($dateRange) {
                if (is_array($dateRange)) {
                    $query->whereBetween('date', $dateRange);
                } else {
                    $query->where('date', $dateRange);
                }
            })
            ->get()->toArray();
        return Response::sendData($data);
    }

    /**
     * @api {get} /statistics/game/serial 多业务流水统计
     *
     * @apiGroup 数据看板-数据看板
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": [
    {
    "date": "2021-09-22", 日期
    "lucky_tree_serial": 410, 许愿流星
    "scramble_sugar_serial": 0, 抢糖
    "huoke_serial": 0 霍克城堡
    }
    ],
    "message": ""
    }
     */
    public function gameSerial(Request $request)
    {
        $fields = ['date_tag', 'start_date', 'end_date'];
        $params = $request->only($fields);
        Validator::paramVerify($fields, $params);

        $dateTag = $params['date_tag'] ?? -1;
        $startDate = $params['start_date'] ?? '';
        $endDate = $params['end_date'] ?? '';

        //计算日期范围
        $dateRange = DateTime::getDateRangeByTag($dateTag, $startDate, $endDate);

        $data = app('model_system_everyday_serial')
            ->select('date', 'lucky_tree_serial', 'scramble_sugar_serial', 'huoke_serial')
            ->where(function ($query) use ($dateRange) {
                if (is_array($dateRange)) {
                    $query->whereBetween('date', $dateRange);
                } else {
                    $query->where('date', $dateRange);
                }
            })
            ->get()->toArray();
        return Response::sendData($data);
    }

    /**
     * @api {get} /statistics/game/user-data 游戏用户数据
     *
     * @apiGroup 数据看板-数据看板
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": [
    {
    "game_no": 1,
    "game_count": "114", 游戏次数
    "people_count": "2", 人数
    "input_gold": "460000", 投入金币数
    "output_gold": "243578", 产出金币数
    "game_name": "许愿流星" 游戏名称
    },
    {
    "game_no": 2,
    "game_count": "3",
    "people_count": "1",
    "input_gold": "13000",
    "output_gold": "13000",
    "game_name": "抢糖"
    },
    {
    "game_no": 3,
    "game_count": "8",
    "people_count": "8",
    "input_gold": "99",
    "output_gold": "20",
    "game_name": "霍克城堡"
    }
    ],
    "message": ""
    }
     */
    public function gameUserData(Request $request)
    {
        $fields = ['date_tag', 'start_date', 'end_date'];
        $params = $request->only($fields);
        Validator::paramVerify($fields, $params);

        $dateTag = $params['date_tag'] ?? -1;
        $startDate = $params['start_date'] ?? '';
        $endDate = $params['end_date'] ?? '';

        //计算日期范围
        $dateRange = DateTime::getDateRangeByTag($dateTag, $startDate, $endDate);

        $data = app('model_statistics_game_data')
            ->select('game_no', DB::raw('sum(game_count) as game_count, sum(people_count) as people_count, sum(input_gold) as input_gold, sum(output_gold) as output_gold'))
            ->where(function ($query) use ($dateRange) {
                if (is_array($dateRange)) {
                    $query->whereBetween('date', $dateRange);
                } else {
                    $query->where('date', $dateRange);
                }
            })
            ->groupBy('game_no')
            ->get()->toArray();
        foreach ($data as &$v) {
            $v['game_name'] = GameEnum::GAME_NO[$v['game_no']];
        }
        return Response::sendData($data);
    }

    /**
     * @api {get} /statistics/serial-total 业务流水占比
     *
     * @apiGroup 数据看板-数据看板
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": {
    "room_gift_serial": "160424583", 礼物流水
    "blind_box_serial": "11110435", 盲盒流水
    "lucky_tree_serial": "10065350", 许愿流星流水
    "scramble_sugar_serial": "0", 抢糖流水
    "huoke_serial": "394074" 霍克城堡流水
    },
    "message": ""
    }
     */
    public function serialTotal(Request $request)
    {
        $fields = ['date_tag', 'start_date', 'end_date'];
        $params = $request->only($fields);
        Validator::paramVerify($fields, $params);

        $dateTag = $params['date_tag'] ?? -1;
        $startDate = $params['start_date'] ?? '';
        $endDate = $params['end_date'] ?? '';

        //计算日期范围
        $dateRange = DateTime::getDateRangeByTag($dateTag, $startDate, $endDate);

        $fieldSum = $fieldSumTotal = '';
        foreach ($this->serialFields as $field) {
            $fieldSum .= "sum($field) as $field,";
        }
        $fieldSum = rtrim($fieldSum, ',');
        $data = app('model_system_everyday_serial')
            ->select(DB::raw($fieldSum))
            ->where(function ($query) use ($dateRange) {
                if (is_array($dateRange)) {
                    $query->whereBetween('date', $dateRange);
                } else {
                    $query->where('date', $dateRange);
                }
            })
            ->first();
        return Response::sendData($data);
    }

    /**
     * @api {get} /statistics/user/count 用户转化漏斗
     *
     * @apiGroup 数据看板-数据看板
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": {
    "register_count": "4", 注册人数
    "login_count": "10", 登录人数
    "recharge_count": "0" 充值人数
    },
    "message": ""
    }
     */
    public function userCount(Request $request)
    {
        $fields = ['date_tag', 'start_date', 'end_date'];
        $params = $request->only($fields);
        Validator::paramVerify($fields, $params);

        $dateTag = $params['date_tag'] ?? -1;
        $startDate = $params['start_date'] ?? '';
        $endDate = $params['end_date'] ?? '';

        //计算日期范围
        $dateRange = DateTime::getDateRangeByTag($dateTag, $startDate, $endDate);

        $data = app('model_statistics_user_count')
            ->select(DB::raw('sum(register_count) as register_count, sum(login_count) as login_count, sum(recharge_count) as recharge_count'))
            ->where(function ($query) use ($dateRange) {
                if (is_array($dateRange)) {
                    $query->whereBetween('date', $dateRange);
                } else {
                    $query->where('date', $dateRange);
                }
            })
            ->first();

        return Response::sendData($data);
    }

    /**
     * 最近数据
     * @param Request $request
     * @return string
     * @throws BasicException
     */
    public function recentlyData(Request $request)
    {
        $params = $request->only('date_tag','data_type');
        $v = app('validator')->make($params, [
            'date_tag' => 'required|integer|in:1,2', // 1日 2周
            'data_type' => 'required|integer|in:1,2,3,4,5,6,7', // 数据类型1房间流水 2盲盒 3鱼跃龙门 4抢麦 5星之许愿池 6星际探险 7总计流水
        ]);
        if ($v->fails()) throw new BasicException(0, $v->errors()->first());

        $list = [];
        $field = '*';
        switch ($params['data_type']) {
            case 1:
                $field = 'room_gift_serial';
                break;
            case 2:
                $field = 'blind_box_serial';
                break;
            case 3:
                $field = 'lucky_tree_serial';
                break;
            case 4:
                $field = 'scramble_sugar_serial';
                break;
            case 5:
                $field = 'star_wishing_serial';
                break;
            case 6:
                $field = 'ad_astra_serial';
                break;
            case 7:
                $fields = $this->serialFields;
                $formatFields = $fieldTotal = '';
                foreach ($fields as $field) {
                    $formatFields .= "sum($field) as $field,";
                    $fieldTotal .= "sum($field)+";
                }
                $fieldTotal = rtrim($fieldTotal, '+') . ' as total';
                $field = DB::raw($fieldTotal);
                break;
        }
        if ($params['date_tag'] == 1) {
            $field = [$field,'date'];
            // 近七日數據
            $list = app('model_system_everyday_serial')
                ->select($field)
                ->orderBy('date','desc')
                ->groupBy('date')
                ->limit(7)
                ->get()->toArray();
            foreach ($list as &$value) {
                if ($params['data_type'] == 7){
                    $value['all_serial'] = $value['total'];
                    unset($value['total']);
                }else{
                    $value['all_serial'] = $value[$field[0]];
                    unset($value[$field[0]]);
                }
            }
        } else {
            $field = 'total';
            $oneWeekDateRange = DateTime::getWeekDateRange();
            $data = app('model_system_everyday_serial')->getSum($this->serialFields, $oneWeekDateRange);
            $list[0]['all_serial'] = $data[$field];
            $list[0]['date'] = $oneWeekDateRange[0].'~'.$oneWeekDateRange[1];
            $twoWeekDateRange = DateTime::getWeekDateRange(-1);
            $data = app('model_system_everyday_serial')->getSum($this->serialFields, $twoWeekDateRange);
            $list[1]['all_serial'] = $data[$field];
            $list[1]['date'] = $twoWeekDateRange[0].'~'.$twoWeekDateRange[1];
            $threeWeekDateRange = DateTime::getWeekDateRange(-2);
            $data = app('model_system_everyday_serial')->getSum($this->serialFields, $threeWeekDateRange);
            $list[2]['all_serial'] = $data[$field];
            $list[2]['date'] = $threeWeekDateRange[0].'~'.$threeWeekDateRange[1];
            $fourWeekDateRange = DateTime::getWeekDateRange(-3);
            $data = app('model_system_everyday_serial')->getSum($this->serialFields, $fourWeekDateRange);
            $list[3]['all_serial'] = $data[$field];
            $list[3]['date'] = $fourWeekDateRange[0].'~'.$fourWeekDateRange[1];
        }
        return Response::sendData($list);
    }
}
